﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using A.BLL;
using System.Data;
using MCData;
using System.Threading;

namespace GetData
{
    public class CsGetBao
    {/*
        A.BLL.newsContent content1 = new A.BLL.newsContent();
        MCdata mCdata = new MCdata();
        DataSet dsget = new DataSet();
        DataTable dtget = new DataTable();
        List<Cs_struct_bao.stc_bao> stc_Baos = new List<Cs_struct_bao.stc_bao>();
        Dictionary<string, object> Dic_val_vlues = new Dictionary<string, object>();
        List<Cs_struct_bao.stc_bao> M_liststc_Bao = new List<Cs_struct_bao.stc_bao>();//最终所有包的集合
        List<Cs_struct_bao.stc_bao> liststc_Bao = new List<Cs_struct_bao.stc_bao>();//最终所有包的集合
        DataTable M_dtselect = new DataTable();
        public string DevPlcIP = "";
        public int DevPlcIPoint = 0;
        public static string Devicename = "";
        //Cs_struct_bao structcs = new Cs_struct_bao();
        struct stc_adrtype
        {
            public static List<string> LL_TEXT_STR = new List<string>();
            public static List<string> L_TEXT = new List<string>();
            public static List<string> Device = new List<string>();
        }
        public CsGetBao(MCdata MCdata, string Devicename_, string plcip_, int plcipoint_)
        {
            this.mCdata = MCdata;
            Devicename = Devicename_;
            DevPlcIP = plcip_;
            DevPlcIPoint = plcipoint_;
        }
        /// <summary>
        /// 打包函数
        /// </summary>
        /// <returns></returns>
        public List<Cs_struct_bao.stc_bao> GetBao()
        {
            List<Cs_struct_bao.stc_bao> liststc_Bao = new List<Cs_struct_bao.stc_bao>();//最终所有包的集合
            List<Cs_struct_bao.stc_bao_tag> listBao_Tags = new List<Cs_struct_bao.stc_bao_tag>();//每60暂存的变量包的集合
            Cs_struct_bao.stc_bao_tag bao_Tag;//包属性结构体对象实例
            Cs_struct_bao.stc_bao stc_Bao;//包结构体对象实例
            try
            {
                //获取数据库中变量的所有数据
                dsget = content1.GO_PROC();
                dtget = dsget.Tables[0];
                DataSet dstype = new DataSet();
                DataSet dstype_string = new DataSet();
                DataTable dt_typecopy = dtget.Clone();
                Dictionary<string, string> dic_type = new Dictionary<string, string>();
                int num = 0;
                //计算所有数据总共按照数据类型和寄存器名可以分为几种情况
                for (int i = 0; i < dtget.Rows.Count; i++)
                {
                    string LL_TEXT_STR = dtget.Rows[i]["LL_TEXT_STR"].ToString();
                    string L_TEXT = dtget.Rows[i]["L_TEXT"].ToString();
                    string Device = dtget.Rows[i]["Device"].ToString();
                    bool matching = false;
                    if (i == 0)
                    {
                        stc_adrtype.LL_TEXT_STR.Add(LL_TEXT_STR);
                        stc_adrtype.L_TEXT.Add(L_TEXT);
                        stc_adrtype.Device.Add(Device);
                        dt_typecopy.ImportRow(dtget.Rows[i]);
                        num++;
                    }
                    else
                    {
                        for (int n = 0; n < dt_typecopy.Rows.Count; n++)
                        {
                            string LL_TEXT_STR_copy = dt_typecopy.Rows[n]["LL_TEXT_STR"].ToString().Trim();
                            string L_TEXT_copy = dt_typecopy.Rows[n]["L_TEXT"].ToString().Trim();
                            string Device_copy = dt_typecopy.Rows[n]["Device"].ToString().Trim();
                            if (LL_TEXT_STR == LL_TEXT_STR_copy && L_TEXT == L_TEXT_copy && Device == Device_copy)
                            {
                                matching = true;
                            }
                        }
                        if (!matching)
                        {
                            stc_adrtype.LL_TEXT_STR.Add(LL_TEXT_STR);
                            stc_adrtype.L_TEXT.Add(L_TEXT);
                            stc_adrtype.Device.Add(Device);
                            dt_typecopy.ImportRow(dtget.Rows[i]);
                            num++;
                        }
                    }


                }
                //按照上述的种类将每一类数据放到一个dataset的一个datatable中保存起来
                for (int j = 0; j < stc_adrtype.LL_TEXT_STR.Count; j++)
                {
                    if (stc_adrtype.L_TEXT[j].ToLower() != "string")
                    {
                        DataTable dt1 = new DataTable();
                        dt1 = dtget.Clone();
                        dt1.TableName = stc_adrtype.LL_TEXT_STR[j] + stc_adrtype.L_TEXT[j] + stc_adrtype.Device[j];
                        for (int i = 0; i < dtget.Rows.Count; i++)
                        {
                            string LL_TEXT_STR = dtget.Rows[i]["LL_TEXT_STR"].ToString();
                            string L_TEXT = dtget.Rows[i]["L_TEXT"].ToString();
                            string Device = dtget.Rows[i]["Device"].ToString();
                            if (LL_TEXT_STR == stc_adrtype.LL_TEXT_STR[j] && L_TEXT == stc_adrtype.L_TEXT[j] && Device == stc_adrtype.Device[j])
                            {
                                // drq.ItemArray = dtget.Rows[i].ItemArray;//这是加入的是第一行
                                dt1.ImportRow(dtget.Rows[i]);
                            }
                        }
                        if (!dstype.Tables.Contains(dt1.TableName))
                        {
                            dstype.Tables.Add(dt1);
                        }
                    }
                    else
                    {
                        DataTable dt_string = new DataTable();
                        dt_string = dtget.Clone();
                        dt_string.TableName = stc_adrtype.LL_TEXT_STR[j] + stc_adrtype.L_TEXT[j] + stc_adrtype.Device[j];
                        for (int i = 0; i < dtget.Rows.Count; i++)
                        {
                            string LL_TEXT_STR = dtget.Rows[i]["LL_TEXT_STR"].ToString();
                            string L_TEXT = dtget.Rows[i]["L_TEXT"].ToString();
                            string Device = dtget.Rows[i]["Device"].ToString();
                            if (LL_TEXT_STR == stc_adrtype.LL_TEXT_STR[j] && L_TEXT == stc_adrtype.L_TEXT[j] && Device == stc_adrtype.Device[j])
                            {
                                // drq.ItemArray = dtget.Rows[i].ItemArray;//这是加入的是第一行
                                dt_string.ImportRow(dtget.Rows[i]);
                            }
                        }
                        if (!dstype_string.Tables.Contains(dt_string.TableName))
                        {
                            dstype_string.Tables.Add(dt_string);
                        }

                    }
                }
                //将每一种除string类型数据按照60的间距打包，把所有打包好的变量包和属性值放到包的结构体集合中
                for (int i = 0; i < dstype.Tables.Count; i++)//遍历所有类型的缓存表
                {
                    for (int j = 0; j < dstype.Tables[i].Rows.Count; j++)//遍历每种类型缓存表的所有行
                    {
                        bao_Tag.iTAG_ID = int.Parse(dstype.Tables[i].Rows[j]["TAG_ID"].ToString());
                        bao_Tag.strTAG_NAME = dstype.Tables[i].Rows[j]["TAG_NAME"].ToString();
                        bao_Tag.iLL_TEXT_num = int.Parse(dstype.Tables[i].Rows[j]["LL_TEXT_num"].ToString());
                        bao_Tag.strLL_TEXT = dstype.Tables[i].Rows[j]["LL_TEXT"].ToString();
                        bao_Tag.strLL_TEXT_TYPE = dstype.Tables[i].Rows[j]["L_TEXT"].ToString();
                        bao_Tag.strDeviceName = dstype.Tables[i].Rows[j]["Device"].ToString();
                        bao_Tag.strVAL_VALUES = "";
                        listBao_Tags.Add(bao_Tag);//将属于一个包的包属性结构体添加到定义的包属性集合中
                        if ((bao_Tag.iLL_TEXT_num - listBao_Tags[0].iLL_TEXT_num) > 60)//将与本次包的起始编号在60以内的变量先打包成一个包
                        {
                            listBao_Tags.Remove(listBao_Tags.Last());//最后一个不属于本包先清除
                            stc_Bao.listbao_tag = new List<Cs_struct_bao.stc_bao_tag>();
                            stc_Bao.iHeadNum = listBao_Tags[0].iLL_TEXT_num;//本包的起始变量数字编号
                            stc_Bao.strHeadval = listBao_Tags[0].strLL_TEXT;//本包的起始变量数字编号
                            stc_Bao.strType = dstype.Tables[i].Rows[j]["L_TEXT"].ToString();//本包的数据类型
                            stc_Bao.strDeviceName = dstype.Tables[i].Rows[j]["Device"].ToString();//本包的数据类型
                            stc_Bao.iLenRead = listBao_Tags.Last().iLL_TEXT_num - listBao_Tags[0].iLL_TEXT_num + 1;//本包起始到结束的编号长度差
                            listBao_Tags.ForEach(n => stc_Bao.listbao_tag.Add(n));//将定义的包属性结构体集合复制给本次包结构体中包属性集合的对象，注意一定要按照这样复制
                            liststc_Bao.Add(stc_Bao);//将本次包结构体添加到定义的包结构体集合中
                            listBao_Tags.Clear();//清除定义的包属性结构体集合重新开始打包下一个包属性集合
                            listBao_Tags.Add(bao_Tag);//先把刚才删除的最后一个包属性结构体元素添加回来作为下一个包的起始值
                        }
                        if (dstype.Tables[i].Rows.Count == (j + 1))//每种类型的最后一个包要特别处理
                        {
                            stc_Bao.listbao_tag = new List<Cs_struct_bao.stc_bao_tag>();
                            stc_Bao.iHeadNum = listBao_Tags[0].iLL_TEXT_num;
                            stc_Bao.strHeadval = listBao_Tags[0].strLL_TEXT;
                            stc_Bao.strType = dstype.Tables[i].Rows[j]["L_TEXT"].ToString();
                            stc_Bao.strDeviceName = dstype.Tables[i].Rows[j]["Device"].ToString();
                            stc_Bao.iLenRead = listBao_Tags.Last().iLL_TEXT_num - listBao_Tags[0].iLL_TEXT_num + 1;
                            listBao_Tags.ForEach(n => stc_Bao.listbao_tag.Add(n));
                            liststc_Bao.Add(stc_Bao);
                            listBao_Tags.Clear();
                        }
                    }
                }
                //将每一种string类型数据按照60的间距打包，把所有打包好的变量包和属性值放到包的结构体集合中
                for (int i = 0; i < dstype_string.Tables.Count; i++)//遍历所有类型的缓存表
                {
                    removeEmpty(dstype_string.Tables[i]);
                    for (int j = 0; j < dstype_string.Tables[i].Rows.Count; j++)//遍历每种类型缓存表的所有行
                    {
                        bao_Tag.iTAG_ID = int.Parse(dstype_string.Tables[i].Rows[j]["TAG_ID"].ToString());
                        bao_Tag.strTAG_NAME = dstype_string.Tables[i].Rows[j]["TAG_NAME"].ToString();
                        bao_Tag.iLL_TEXT_num = int.Parse(dstype_string.Tables[i].Rows[j]["LL_TEXT_num"].ToString());
                        bao_Tag.strLL_TEXT = dstype_string.Tables[i].Rows[j]["LL_TEXT"].ToString();
                        bao_Tag.strLL_TEXT_TYPE = dstype_string.Tables[i].Rows[j]["L_TEXT"].ToString();
                        bao_Tag.strDeviceName = dstype_string.Tables[i].Rows[j]["Device"].ToString();
                        bao_Tag.strVAL_VALUES = "";
                        listBao_Tags.Add(bao_Tag);//将属于一个包的包属性结构体添加到定义的包属性集合中

                        stc_Bao.listbao_tag = new List<Cs_struct_bao.stc_bao_tag>();
                        stc_Bao.iHeadNum = listBao_Tags[0].iLL_TEXT_num;//本包的起始变量数字编号
                        stc_Bao.strHeadval = listBao_Tags[0].strLL_TEXT;//本包的起始变量数字编号
                        stc_Bao.strType = dstype_string.Tables[i].Rows[j]["L_TEXT"].ToString();//本包的数据类型
                        stc_Bao.strDeviceName = dstype_string.Tables[i].Rows[j]["Device"].ToString();//本包的数据类型
                        stc_Bao.iLenRead = 0;//本包起始到结束的编号长度差
                        listBao_Tags.ForEach(n => stc_Bao.listbao_tag.Add(n));//将定义的包属性结构体集合复制给本次包结构体中包属性集合的对象，注意一定要按照这样复制
                        liststc_Bao.Add(stc_Bao);//将本次包结构体添加到定义的包结构体集合中
                        listBao_Tags.Clear();//清除定义的包属性结构体集合重新开始打包下一个包属性集合
                    }
                }
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
            return liststc_Bao;
        }
        /// <summary>
        /// 获取变量对应PLC中的值
        /// </summary>
        /// <param name="mCdata"></param>
        /// <returns></returns>
        public Dictionary<string, Cs_struct_bao.stc_bao_tag> GetVal(string DevName, out bool IsReadFalse_)
        {
            IsReadFalse_ = true;
            Dictionary<string, Cs_struct_bao.stc_bao_tag> Dic_stcval = new Dictionary<string, Cs_struct_bao.stc_bao_tag>();
            try
            {
                Cs_struct_bao.stc_bao_tag bao_Tag;//包属性结构体对象实例
                if (liststc_Bao.Count == 0)
                {
                    M_liststc_Bao = GetBao();//获取所有设备的集合包
                    foreach (var item in M_liststc_Bao)
                    {
                        if (item.strDeviceName != DevName)
                        {
                            liststc_Bao.Add(item);//获取不属于这个plc的集合包
                        }
                    }
                    liststc_Bao = M_liststc_Bao.Except(liststc_Bao).ToList();//获取属于这个plc的集合包
                    CsLogFun.WriteToLog("获取寄存器变量包，包中集合数量为:" + liststc_Bao.Count);
                }

                for (int i = 0; i < liststc_Bao.Count; i++)
                {
                    Dictionary<string, object> Dic_val = new Dictionary<string, object>();
                    //string aa = stc_Baos[i].strType.ToLower();
                    if (liststc_Bao[i].strType.ToLower() == "short" && liststc_Bao[i].strDeviceName == DevName)
                    {
                        Dic_val = mCdata.Read(liststc_Bao[i].strHeadval, liststc_Bao[i].iLenRead);
                        if (Dic_val.Count == 0)
                        {
                            if (!mCdata.IsConnect())
                            {
                                CsLogFun.WriteToLog("plc连接失败");
                                mCdata.Close();
                                mCdata.NewTcp(DevPlcIP, DevPlcIPoint);
                            }
                            CsLogFun.WriteToLog("读取plc为空，读取失败,strHeadval:" + liststc_Bao[i].strHeadval + ",iLenRead:" + liststc_Bao[i].iLenRead + "包集合数量:" + liststc_Bao.Count + "包类型：" + liststc_Bao[i].strType);
                            IsReadFalse_ = false;
                            continue;
                        }

                    }
                    //else if (liststc_Bao[i].strType.ToLower() == "long" && liststc_Bao[i].strDeviceName == DevName)
                    //{
                    //    Dic_val = mCdata.Read32bit(liststc_Bao[i].strHeadval, liststc_Bao[i].iLenRead + 1);
                    //}
                    //else if (liststc_Bao[i].strType.ToLower() == "string" && liststc_Bao[i].strDeviceName == DevName)
                    //{

                    //}
                    for (int j = 0; j < liststc_Bao[i].listbao_tag.Count; j++)
                    {
                        string LL_TEXT_name = liststc_Bao[i].listbao_tag[j].strLL_TEXT;
                        for (int s = 0; s < Dic_val.ToList().Count; s++)
                        {
                            string keyval = Dic_val.ToList()[s].Key;
                            if (LL_TEXT_name == keyval)
                            {
                                bao_Tag = liststc_Bao[i].listbao_tag[j];
                                bao_Tag.strVAL_VALUES = Dic_val.ToList()[s].Value.ToString();
                                //liststc_Bao[i].listbao_tag[j] = bao_Tag;//结构使用list赋值一定要整体赋值，即结构体赋值给结构体不能结构体的成员之间赋值
                                Dic_stcval.Add(keyval, bao_Tag);
                            }
                        }
                    }
                }
                for (int t = 0; t < Dic_stcval.ToList().Count; t++)
                {
                    string keyval = Dic_stcval.ToList()[t].Key;
                    Dic_stcval = Dic_stcval.ToDictionary(k => k.Key == keyval ? GetValName(keyval, DevName) : k.Key, k => k.Value);//将Dic_stcval中寄存器地址名替换成变量名
                }
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
            return Dic_stcval;
        }
        /// <summary>
        /// 将寄存器地址转化成对应的变量名
        /// </summary>
        /// <param name="PlcAddr"></param>
        /// <returns></returns>
        public string GetValName(string PlcAddr, string Device)
        {
            string valname = "";
            try
            {
                if (M_dtselect.Rows.Count == 0)
                {
                    string sqlstr = string.Format("SELECT*FROM dbo.MAINTABLE WHERE Device='{0}'", Device);
                    DataSet ds = content1.Select_nothing(sqlstr);
                    M_dtselect = ds.Tables[0];
                }
                for (int i = 0; i < M_dtselect.Rows.Count; i++)
                {
                    if (M_dtselect.Rows[i]["LL_TEXT"].ToString() == PlcAddr && M_dtselect.Rows[i]["Device"].ToString() == Device)
                    {
                        valname = M_dtselect.Rows[i]["TAG_NAME"].ToString();
                    }
                }
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
            return valname;
        }
        /// <summary>
        /// 根据变量名找对应PLC的地址
        /// </summary>
        /// <param name="valname">变量名</param>
        /// <returns></returns>
        public string GetPlcAdrr(string valname, string Device)
        {
            if (M_dtselect.Rows.Count == 0)
            {
                string sqlstr = string.Format("SELECT*FROM dbo.MAINTABLE WHERE Device='{0}'", Device);
                DataSet ds = content1.Select_nothing(sqlstr);
                M_dtselect = ds.Tables[0];
            }
            string plcaddr = "";
            try
            {
                for (int i = 0; i < M_dtselect.Rows.Count; i++)
                {
                    if (M_dtselect.Rows[i]["TAG_NAME"].ToString() == valname && M_dtselect.Rows[i]["Device"].ToString() == Device)
                    {
                        plcaddr = M_dtselect.Rows[i]["LL_TEXT"].ToString();
                    }
                }
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
            return plcaddr;
        }
        /// <summary>
        /// 写入PLC
        /// </summary>
        /// <param name="val_name">变量名称</param>
        public void WriteToPlc(string val_name, Int16 val, string Device)
        {
            try
            {
                string addr = GetPlcAdrr(val_name.Trim(), Device);
                mCdata.Write(GetPlcAdrr(val_name.Trim(), Device), val);
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }

        }
        public void WriteToPlc(string val_name, string strval, string Device)
        {
            try
            {
                mCdata.Write(GetPlcAdrr(val_name.Trim(), Device), strval);
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }

        }
        public void WriteToPlc(string val_name, int qty, int[] arrval, string Device)
        {
            try
            {
                mCdata.Write(GetPlcAdrr(val_name.Trim(), Device), qty, arrval);
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
        }
        public void WriteToPlc(string dress_, int qty, int[] arrval)
        {
            try
            {
                mCdata.Write(dress_, qty, arrval);
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
        }
        public void WriteToPlc(string dress_, string val_)
        {
            try
            {
                int val = int.Parse(val_.ToString());
                mCdata.Write(dress_, val);
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
        }
        /// <summary>
        /// 写入字符串到PLC
        /// </summary>
        /// <param name="dress_">地址</param>
        /// <param name="strdata_">数据</param>
        public void WriteStringToPlc(string dress_, string strdata_)
        {
            try
            {
                //string dress = GetPlcAdrr(val_name.Trim(), Device);
                mCdata.Write(dress_, strdata_);
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
        }
        public string ReadPlcString(string dress_, int Nmber_)
        {
            try
            {
                string strdata = "";
                strdata = mCdata.ReadString(dress_, Nmber_);
                return strdata;
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
        }
        public string ReadPlcString(string val_name, string Device, int Nmber_)
        {
            try
            {
                string strdata = "";
                string dress = GetPlcAdrr(val_name.Trim(), Device);
                strdata = mCdata.ReadString(dress, Nmber_);
                return strdata;
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
        }
        public Dictionary<string, object> ReadPlc(string dress_, int Nmber_)
        {
            try
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                dic = mCdata.Read(dress_, Nmber_);
                return dic;
                //return dic.ToList()[Nmber_-1].Value.ToString();
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }
        }
        public void Write32bitToPlc(string val_name, Int32 val, string Device)
        {
            try
            {
                mCdata.Write32bit(GetPlcAdrr(val_name.Trim(), Device), val);
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }

        }
        /// <summary>
        /// 循环去除datatable中的空行
        /// </summary>
        /// <param name="M_dt"></param>
        protected void removeEmpty(DataTable M_dt)
        {
            try
            {
                List<DataRow> removelist = new List<DataRow>();
                for (int i = 0; i < M_dt.Rows.Count; i++)
                {
                    bool rowdataisnull = true;
                    for (int j = 0; j < M_dt.Columns.Count; j++)
                    {

                        if (!string.IsNullOrEmpty(M_dt.Rows[i][j].ToString().Trim()))
                        {

                            rowdataisnull = false;
                        }

                    }
                    if (rowdataisnull)
                    {
                        removelist.Add(M_dt.Rows[i]);
                    }

                }
                for (int i = 0; i < removelist.Count; i++)
                {
                    M_dt.Rows.Remove(removelist[i]);
                }
            }
            catch (Exception err)
            {
                CsLogFun.WriteToLog(err);
                throw new Exception("提示：" + err.Message);
            }

        }*/
    }
}
